home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / doom / chaserog.zip / SRC_ROG.ZIP / ITEMS.QC < prev    next >
Text File  |  1997-05-02  |  43KB  |  1,938 lines

  1. void() W_SetCurrentAmmo;
  2. /* ALL LIGHTS SHOULD BE 0 1 0 IN COLOR ALL OTHER ITEMS SHOULD
  3. BE .8 .3 .4 IN COLOR */
  4.  
  5.  
  6. void() SUB_regen =
  7. {
  8.     self.model = self.mdl;        // restore original model
  9.     self.solid = SOLID_TRIGGER;    // allow it to be touched again
  10.     sound (self, CHAN_VOICE, "items/itembk2.wav", 1, ATTN_NORM);    // play respawn sound
  11.     setorigin (self, self.origin);
  12. };
  13.  
  14.  
  15.  
  16. /*QUAKED noclass (0 0 0) (-8 -8 -8) (8 8 8)
  17. prints a warning message when spawned
  18. */
  19. void() noclass =
  20. {
  21.     dprint ("noclass spawned at");
  22.     dprint (vtos(self.origin));
  23.     dprint ("\n");
  24.     remove (self);
  25. };
  26.  
  27.  
  28.  
  29. /*
  30. ============
  31. PlaceItem
  32.  
  33. plants the object on the floor
  34. ============
  35. */
  36. void() PlaceItem =
  37. {
  38.     local float    oldz;
  39.  
  40.     self.mdl = self.model;        // so it can be restored on respawn
  41.     self.flags = FL_ITEM;        // make extra wide
  42.     self.solid = SOLID_TRIGGER;
  43.     self.movetype = MOVETYPE_TOSS;    
  44.     self.velocity = '0 0 0';
  45.     self.origin_z = self.origin_z + 6;
  46.     oldz = self.origin_z;
  47.     if (!droptofloor())
  48.     {
  49.         dprint ("Bonus item fell out of level!\n");
  50.         dprint (self.classname);
  51.         dprint (" at ");
  52.         dprint (vtos(self.origin));
  53.         dprint ("\n");
  54.         remove(self);
  55.         return;
  56.     }
  57. };
  58.  
  59. /*
  60. ============
  61. StartItem
  62.  
  63. Sets the clipping size and plants the object on the floor
  64. ============
  65. */
  66. void() StartItem =
  67. {
  68.     self.nextthink = time + 0.2;    // items start after other solids
  69.     self.think = PlaceItem;
  70. };
  71.  
  72. /*
  73. =========================================================================
  74.  
  75. HEALTH BOX
  76.  
  77. =========================================================================
  78. */
  79. //
  80. // T_Heal: add health to an entity, limiting health to max_health
  81. // "ignore" will ignore max_health limit
  82. //
  83. float () T_Heal =
  84. {
  85.     local float cap;
  86.     if ((self.spawnflags & H_MEGA))
  87.     {
  88.         cap = other.max_health * 2.5;
  89.         if (other.health >= cap)
  90.             return FALSE;
  91.         other.health = other.health + self.health;
  92.         if (other.health > cap)
  93.             other.health = cap;
  94.         self.health = 0;
  95.     }
  96.     else
  97.     {
  98.         if (other.health >= other.max_health)
  99.             return FALSE;
  100.  
  101.         other.health = other.health + self.health;
  102.  
  103.         // Rob; items2 alternate rules
  104.         // setup self.health for checking at end of health_touch()
  105.         // (greater than 0 = amount went over the cap)
  106.         if (!deathmatch && (sp_altrules & SP_ITEMS2))
  107.             self.health = other.health - other.max_health;
  108.         else
  109.             self.health = 0;
  110.  
  111.         if (other.health > other.max_health)
  112.             other.health = other.max_health;
  113.     }
  114.  
  115.     return TRUE;
  116. };
  117.  
  118. /*QUAKED item_health (.3 .3 1) (0 0 0) (32 32 32) rotten megahealth
  119. Health box. Normally gives 25 points.
  120. Rotten box heals 5-10 points,
  121. megahealth will add 100 health, then
  122. rot you down to your maximum health limit,
  123. one point per second.
  124. */
  125.  
  126. // Rob;
  127. // (entire health spawn and touch stucture modified below)
  128. //float    H_ROTTEN = 1; // moved to defs.qc
  129. //float    H_MEGA = 2;
  130. // .healamount -> .health
  131. // .healtype -> (just check .spawnflags again, since they're not changed)
  132.  
  133. //.float    healamount, healtype;
  134.  
  135. void() health_touch;
  136. void() item_megahealth_rot;
  137.  
  138. void() item_health =
  139. {
  140.     self.touch = health_touch;
  141.     /*
  142.         (rotten health box)
  143.     precache_model("maps/b_bh10.bsp");
  144.     precache_sound("items/r_item1.wav");
  145.         (normal health box)
  146.     precache_model("maps/b_bh25.bsp");
  147.     precache_sound("items/health1.wav");
  148.     */
  149.     if (self.spawnflags & H_MEGA)
  150.     {
  151.         precache_model("maps/b_bh100.bsp");
  152.         precache_sound("items/r_item2.wav");
  153.         setmodel(self, "maps/b_bh100.bsp");
  154.         self.noise = "items/r_item2.wav";
  155.         self.health = 100;
  156.         self.max_health = 100;
  157.     }
  158.     else
  159.     {
  160.         // both needed if items2 is on
  161.         precache_model("maps/b_bh10.bsp");
  162.         precache_sound("items/r_item1.wav");
  163.         precache_model("maps/b_bh25.bsp");
  164.         precache_sound("items/health1.wav");
  165.  
  166.         if (self.spawnflags & H_ROTTEN)
  167.         {
  168.             setmodel(self, "maps/b_bh10.bsp");
  169.             self.noise = "items/r_item1.wav";
  170.             self.health = 15;
  171.             self.max_health = 15; // .health values modified in all rules, so save for respawns
  172.         }
  173.         else
  174.         {
  175.             setmodel(self, "maps/b_bh25.bsp");
  176.             self.noise = "items/health1.wav";
  177.             self.health = 25;
  178.             self.max_health = 25;
  179.         }
  180.     }
  181.     setsize (self, '0 0 0', '32 32 56');
  182.  
  183.     StartItem ();
  184. };
  185.  
  186. void () bounce_healthbox =
  187. {
  188.     local vector vel, spot;
  189.  
  190.     self.nextthink = time + 0.1;
  191.  
  192.     if    (self.noise == "")
  193.     {
  194.         if (self.velocity == '0 0 0') // set touch back on and exit cycle
  195.         {
  196.             self.touch = health_touch;
  197.             self.noise = "items/r_item1.wav";
  198.             self.nextthink = 0;
  199.             // (take care of mdl origin weirdness when angles modified)
  200.             spot = self.origin; // + '0 0 8';
  201.             traceline( spot, spot - '32 0 0', TRUE, self.owner );
  202.             if (trace_fraction < 1)
  203.             {
  204.                 traceline( trace_endpos, trace_endpos + '32 0 0', TRUE, self.owner );
  205.                 setorigin( self, trace_endpos);
  206.             }
  207.             spot = self.origin;
  208.             traceline( spot, spot - '0 32 0', TRUE, self.owner );
  209.             if (trace_fraction < 1)
  210.             {
  211.                 traceline( trace_endpos, trace_endpos + '0 32 0', TRUE, self.owner );
  212.                 setorigin( self, trace_endpos);
  213.             }
  214.         }
  215.         return;
  216.     }
  217.  
  218.     // start bounce
  219.  
  220.     self.noise = ""; // used for thinking after bounce has started
  221.  
  222.     makevectors( self.owner.v_angle );
  223.     if (random() < 0.5)
  224.         vel = '0 0 0' - v_right * 200;
  225.     else
  226.         vel = v_right * 200;
  227.     vel = vel - v_forward * 200;
  228.     // testing vel
  229.     // vel = v_forward * 100;
  230.  
  231.     vel_z = 250;
  232.  
  233.     if (random() < 0.5)
  234.         self.angles = '-90 0 0';
  235.     else
  236.         self.angles = '0 0 0';
  237.     self.avelocity = '0 200 0';
  238.  
  239.     setmodel(self, "maps/b_bh10.bsp");
  240.     self.movetype = MOVETYPE_BOUNCE;
  241.     self.flags = self.flags - (self.flags & FL_ONGROUND);
  242.     self.velocity = vel;
  243.  
  244. };
  245.  
  246.  
  247. void() health_touch =
  248. {
  249.     local    float oldhealth;
  250.     local    string    s;
  251.  
  252.     if (other.classname != "player")
  253.         return;
  254.     if (other.health <= 0)
  255.         return;
  256.  
  257.     oldhealth = other.health;
  258.  
  259.     if (!T_Heal())
  260.             return;
  261.  
  262.     sprint(other, "You receive ");
  263.     if (!deathmatch && (sp_altrules & SP_ITEMS2))
  264.         s = ftos(other.health - oldhealth);
  265.     else
  266.         s = ftos(self.max_health);
  267.     sprint(other, s);
  268.     sprint(other, " health\n");
  269.  
  270. // health touch sound
  271.     sound(other, CHAN_ITEM, self.noise, 1, ATTN_NORM);
  272.     stuffcmd (other, "bf\n");
  273.  
  274.     activator = other;
  275.     SUB_UseTargets();                // fire all targets / killtargets
  276.  
  277.     // Rob; only alternate rules check in T_Heal() will set higher than 0
  278.     if (self.health < 1)
  279.     {
  280.  
  281.         self.model = string_null;
  282.         self.solid = SOLID_NOT;
  283.  
  284.         // Megahealth = rot down the player's super health
  285.         if ((self.spawnflags & H_MEGA) && !RuneHasElder(other))
  286.         {
  287.             other.items2 = other.items2 | IT2_SUPERHEALTH;
  288.             self.nextthink = time + 5;
  289.             self.think = item_megahealth_rot;
  290.             self.owner = other;
  291.         }
  292.  
  293.         // Megahealth = rot down the player's super health
  294.         //if ((self.spawnflags & H_MEGA))
  295.         //{
  296.         //    other.items = other.items | IT_SUPERHEALTH;
  297.         //    self.nextthink = time + 5;
  298.         //    self.think = item_megahealth_rot;
  299.         //    self.owner = other;
  300.         //}
  301.  
  302.         if (deathmatch && deathmatch != 2) // deathmatch 2 is the silly old rules
  303.         {
  304.             self.health = self.max_health; // reset health amount for DM respawns
  305.             self.nextthink = time + 20;
  306.             self.think = SUB_regen;
  307.         }
  308.         else if (! (self.spawnflags & H_MEGA) )
  309.         {
  310.             remove( self );
  311.             return;
  312.         }
  313.     }
  314.     else
  315.     {
  316.         self.touch = SUB_Null; // turn off touch until bounce think reables
  317.         self.owner = other;
  318.         self.nextthink = time + 0.1;
  319.         self.think = bounce_healthbox;
  320.     }
  321.  
  322. };
  323.  
  324.  
  325.  
  326. // ####
  327. /*
  328. void() item_health =
  329. {
  330.     self.touch = health_touch;
  331.  
  332.     if (self.spawnflags & H_ROTTEN)
  333.     {
  334.         precache_model("maps/b_bh10.bsp");
  335.  
  336.         precache_sound("items/r_item1.wav");
  337.         setmodel(self, "maps/b_bh10.bsp");
  338.         self.noise = "items/r_item1.wav";
  339.         self.healamount = 15;
  340.         self.healtype = 0;
  341.     }
  342.     else
  343.     if (self.spawnflags & H_MEGA)
  344.     {
  345.         precache_model("maps/b_bh100.bsp");
  346.         precache_sound("items/r_item2.wav");
  347.         setmodel(self, "maps/b_bh100.bsp");
  348.         self.noise = "items/r_item2.wav";
  349.         self.healamount = 100;
  350.         self.healtype = 2;
  351.     }
  352.     else
  353.     {
  354.         precache_model("maps/b_bh25.bsp");
  355.         precache_sound("items/health1.wav");
  356.         setmodel(self, "maps/b_bh25.bsp");
  357.         self.noise = "items/health1.wav";
  358.         self.healamount = 25;
  359.         self.healtype = 1;
  360.     }
  361.     setsize (self, '0 0 0', '32 32 56');
  362.     StartItem ();
  363. };
  364.  
  365.  
  366. void() health_touch =
  367. {
  368.     local    float amount;
  369.     local    string    s;
  370.  
  371.     if (other.classname != "player")
  372.         return;
  373.  
  374.     if (self.healtype == 2) // Megahealth?  Ignore max_health...
  375.     {
  376.         if (other.health >= 250)
  377.             return;
  378.         if (!T_Heal(other, self.healamount, 1))
  379.             return;
  380.     }
  381.     else
  382.     {
  383.         if (!T_Heal(other, self.healamount, 0))
  384.             return;
  385.     }
  386.  
  387.     sprint(other, "You receive ");
  388.     s = ftos(self.healamount);
  389.     sprint(other, s);
  390.     sprint(other, " health\n");
  391.  
  392. // health touch sound
  393.     sound(other, CHAN_ITEM, self.noise, 1, ATTN_NORM);
  394.  
  395.     stuffcmd (other, "bf\n");
  396.  
  397.     self.model = string_null;
  398.     self.solid = SOLID_NOT;
  399.  
  400.     // Megahealth = rot down the player's super health
  401.     if (self.healtype == 2 && !RuneHasElder(other))
  402.     {
  403.         other.items2 = other.items2 | IT2_SUPERHEALTH;
  404.         self.nextthink = time + 5;
  405.         self.think = item_megahealth_rot;
  406.         self.owner = other;
  407.     }
  408.     else
  409.     {
  410.         if (deathmatch != 2)        // deathmatch 2 is the silly old rules
  411.         {
  412.             if (deathmatch)
  413.                 self.nextthink = time + 20;
  414.             self.think = SUB_regen;
  415.         }
  416.     }
  417.  
  418.     activator = other;
  419.     SUB_UseTargets();                // fire all targets / killtargets
  420. };
  421. // ####
  422. */
  423.  
  424.  
  425. void() item_megahealth_rot =
  426. {
  427.     other = self.owner;
  428.  
  429.     if (other.health > other.max_health)
  430.     {
  431.         other.health = other.health - 1;
  432.         self.nextthink = time + 1;
  433.         return;
  434.     }
  435.  
  436. // it is possible for a player to die and respawn between rots, so don't
  437. // just blindly subtract the flag off
  438.     other.items2 = other.items2 - (other.items2 & IT2_SUPERHEALTH);
  439.  
  440.     if (deathmatch == 1)    // deathmatch 2 is silly old rules
  441.     {
  442.         self.nextthink = time + 20;
  443.         self.think = SUB_regen;
  444.     }
  445. };
  446.  
  447. /*
  448. ===============================================================================
  449.  
  450. ARMOR
  451.  
  452. ===============================================================================
  453. */
  454.  
  455. void() armor_touch;
  456.  
  457. void() armor_touch =
  458. {
  459.     local    float    type, value, bit;
  460.     
  461.     if (other.health <= 0)
  462.         return;
  463.     if (other.classname != "player")
  464.         return;
  465.  
  466.     if (self.classname == "item_armor1")
  467.     {
  468.         type = 0.3;
  469.         value = 100;
  470.         bit = IT2_ARMOR1;
  471.     }
  472.     if (self.classname == "item_armor2")
  473.     {
  474.         type = 0.6;
  475.         value = 150;
  476.         bit = IT2_ARMOR2;
  477.     }
  478.     if (self.classname == "item_armorInv")
  479.     {
  480.         type = 0.8;
  481.         value = 200;
  482.         bit = IT2_ARMOR3;
  483.     }
  484.     if (other.armortype*other.armorvalue >= type*value)
  485.         return;
  486.         
  487.     other.armortype = type;
  488.     other.armorvalue = value;
  489.     other.items2 = other.items2 - 
  490.                 (other.items2 & (IT2_ARMOR1 | IT2_ARMOR2 | IT2_ARMOR3)) + bit;
  491.  
  492.     self.solid = SOLID_NOT;
  493.     self.model = string_null;
  494.     if (deathmatch == 1)
  495.         self.nextthink = time + 20;
  496.     self.think = SUB_regen;
  497.  
  498.     sprint(other, "You got armor\n");
  499. // armor touch sound
  500.     sound(other, CHAN_ITEM, "items/armor1.wav", 1, ATTN_NORM);
  501.     stuffcmd (other, "bf\n");
  502.     
  503.     activator = other;
  504.     SUB_UseTargets();                // fire all targets / killtargets
  505. };
  506.  
  507.  
  508. /*QUAKED item_armor1 (0 .5 .8) (-16 -16 0) (16 16 32)
  509. */
  510.  
  511. void() item_armor1 =
  512. {
  513.     self.touch = armor_touch;
  514.     precache_model ("progs/armor.mdl");
  515.     setmodel (self, "progs/armor.mdl");
  516.     self.skin = 0;
  517.     setsize (self, '-16 -16 0', '16 16 56');
  518.     StartItem ();
  519. };
  520.  
  521. /*QUAKED item_armor2 (0 .5 .8) (-16 -16 0) (16 16 32)
  522. */
  523.  
  524. void() item_armor2 =
  525. {
  526.     self.touch = armor_touch;
  527.     precache_model ("progs/armor.mdl");
  528.     setmodel (self, "progs/armor.mdl");
  529.     self.skin = 1;
  530.     setsize (self, '-16 -16 0', '16 16 56');
  531.     StartItem ();
  532. };
  533.  
  534. /*QUAKED item_armorInv (0 .5 .8) (-16 -16 0) (16 16 32)
  535. */
  536.  
  537. void() item_armorInv =
  538. {
  539.     self.touch = armor_touch;
  540.     precache_model ("progs/armor.mdl");
  541.     setmodel (self, "progs/armor.mdl");
  542.     self.skin = 2;
  543.     setsize (self, '-16 -16 0', '16 16 56');
  544.     StartItem ();
  545. };
  546.  
  547. /*
  548. ===============================================================================
  549.  
  550. WEAPONS
  551.  
  552. ===============================================================================
  553. */
  554.  
  555. void() bound_other_ammo =
  556. {
  557.     if (other.ammo_shells1 > 100)
  558.         other.ammo_shells1 = 100;
  559.     if (other.ammo_nails1 > 200)
  560.         other.ammo_nails1 = 200;
  561.     if (other.ammo_rockets1 > 100)
  562.         other.ammo_rockets1 = 100;        
  563.     if (other.ammo_cells1 > 100)
  564.         other.ammo_cells1 = 100;        
  565.         
  566.     // PGM addition
  567.     if (other.ammo_lava_nails > 200)
  568.         other.ammo_lava_nails = 200;
  569.     if (other.ammo_multi_rockets > 100)
  570.         other.ammo_multi_rockets = 100;
  571.     if (other.ammo_plasma > 100)
  572.         other.ammo_plasma = 100;
  573. };
  574.  
  575.  
  576. float(float w) RankForWeapon =
  577. {
  578.     if (w == IT_PLASMA_GUN)
  579.         return 1;
  580.     if (w == IT_LIGHTNING)
  581.         return 2;
  582.     if (w == IT_MULTI_ROCKET)
  583.         return 3;
  584.     if (w == IT_ROCKET_LAUNCHER)
  585.         return 4;
  586.     if (w == IT_LAVA_SUPER_NAILGUN)
  587.         return 5;
  588.     if (w == IT_SUPER_NAILGUN)
  589.         return 6;
  590.     if (w == IT_MULTI_GRENADE)
  591.         return 7;
  592.     if (w == IT_GRENADE_LAUNCHER)
  593.         return 8;
  594.     if (w == IT_LAVA_NAILGUN)
  595.         return 9;
  596.     if (w == IT_SUPER_SHOTGUN)
  597.         return 10;
  598.     if (w == IT_NAILGUN)
  599.         return 11;
  600.     return 12;
  601. };
  602.  
  603. /*
  604. =============
  605. Deathmatch_Weapon
  606.  
  607. Deathmatch weapon change rules for picking up a weapon
  608.  
  609. .float        ammo_shells1, ammo_nails1, ammo_rockets1, ammo_cells1;
  610. =============
  611. */
  612. void(float old, float new) Deathmatch_Weapon =
  613. {
  614.     local float or, nr;
  615.  
  616. // PGM - fix for changing to weapons when grappling.
  617.     if (self.weapon == IT_GRAPPLE && self.button0)
  618.         return;
  619.  
  620. // change self.weapon if desired
  621.     or = RankForWeapon (self.weapon);
  622.     nr = RankForWeapon (new);
  623.     if ( nr < or )
  624.         self.weapon = new;
  625. };
  626.  
  627. void(entity comboOwner) EnableComboWeapons =
  628. {
  629.     if (comboOwner.classname != "player")
  630.         return;
  631.     
  632.     if (!(comboOwner.items & IT_LAVA_NAILGUN))
  633.     {
  634.         if (comboOwner.ammo_lava_nails > 0 && (comboOwner.items & IT_NAILGUN))
  635.         {
  636.             sprint (comboOwner, "Lava Enabled\n");
  637.             comboOwner.items = comboOwner.items | IT_LAVA_NAILGUN;
  638.         }
  639.     }
  640.  
  641.     if (!(comboOwner.items & IT_LAVA_SUPER_NAILGUN))
  642.     {
  643.         if (comboOwner.ammo_lava_nails > 0 && 
  644.                             (comboOwner.items & IT_SUPER_NAILGUN))
  645.         {
  646.             sprint (comboOwner, "Super Lava Enabled\n");
  647.             comboOwner.items = comboOwner.items | IT_LAVA_SUPER_NAILGUN;        
  648.         }
  649.     }
  650.  
  651.     if (!(comboOwner.items & IT_MULTI_GRENADE))
  652.     {
  653.         if (comboOwner.ammo_multi_rockets > 0 && 
  654.                             (comboOwner.items & IT_GRENADE_LAUNCHER))
  655.         {
  656.             sprint (comboOwner, "Multi Grenades Enabled\n");
  657.             comboOwner.items = comboOwner.items | IT_MULTI_GRENADE;        
  658.         }
  659.     }
  660.  
  661.     if (!(comboOwner.items & IT_MULTI_ROCKET))
  662.     {
  663.         if (comboOwner.ammo_multi_rockets > 0 && 
  664.                             (comboOwner.items & IT_ROCKET_LAUNCHER))
  665.         {
  666.             sprint (comboOwner, "Multi Rockets Enabled\n");
  667.             comboOwner.items = comboOwner.items | IT_MULTI_ROCKET;        
  668.         }
  669.     }
  670.  
  671.     if (!(comboOwner.items & IT_PLASMA_GUN))
  672.     {
  673.         if (comboOwner.ammo_plasma > 0 && (comboOwner.items & IT_LIGHTNING))
  674.         {
  675.             sprint (comboOwner, "Plasma Gun Enabled\n");
  676.             comboOwner.items = comboOwner.items | IT_PLASMA_GUN;        
  677.         }
  678.     }
  679. };
  680.  
  681. /*
  682. =============
  683. weapon_touch
  684. =============
  685. */
  686. float() W_BestWeapon;
  687.  
  688. void() weapon_touch =
  689. {
  690.     local    float    hadammo, best, new, old;
  691.     local    entity    stemp;
  692.     local    float    leave;
  693.  
  694.     if (!(other.flags & FL_CLIENT))
  695.         return;
  696.  
  697. // if the player was using his best weapon, change up to the new one if better        
  698.     stemp = self;
  699.     self = other;
  700.     best = W_BestWeapon();
  701.     self = stemp;
  702.  
  703.     if (deathmatch == 2 || coop)
  704.         leave = 1;
  705.     else
  706.         leave = 0;
  707.     
  708.     if (self.classname == "weapon_nailgun")
  709.     {
  710.         if (leave && (other.items & IT_NAILGUN) )
  711.             return;
  712.         hadammo = other.ammo_nails1;            
  713.         new = IT_NAILGUN;
  714.         if (leave)
  715.             other.ammo_lava_nails = other.ammo_lava_nails + 20;
  716.         other.ammo_nails1 = other.ammo_nails1 + 30;
  717.     }
  718.     else if (self.classname == "weapon_supernailgun")
  719.     {
  720.         if (leave && (other.items & IT_SUPER_NAILGUN) )
  721.             return;
  722.         hadammo = other.ammo_rockets1;            
  723.         new = IT_SUPER_NAILGUN;
  724.         if (leave)
  725.             other.ammo_lava_nails = other.ammo_lava_nails + 20;
  726.         other.ammo_nails1 = other.ammo_nails1 + 30;
  727.     }
  728.     else if (self.classname == "weapon_supershotgun")
  729.     {
  730.         if (leave && (other.items & IT_SUPER_SHOTGUN) )
  731.             return;
  732.         hadammo = other.ammo_rockets1;            
  733.         new = IT_SUPER_SHOTGUN;
  734.         other.ammo_shells1 = other.ammo_shells1 + 5;
  735.     }
  736.     else if (self.classname == "weapon_rocketlauncher")
  737.     {
  738.         if (leave && (other.items & IT_ROCKET_LAUNCHER) )
  739.             return;
  740.         hadammo = other.ammo_rockets1;            
  741.         new = IT_ROCKET_LAUNCHER;
  742.         if (leave)
  743.             other.ammo_multi_rockets = other.ammo_multi_rockets + 3;
  744.         other.ammo_rockets1 = other.ammo_rockets1 + 5;
  745.     }
  746.     else if (self.classname == "weapon_grenadelauncher")
  747.     {
  748.         if (leave && (other.items & IT_GRENADE_LAUNCHER) )
  749.             return;
  750.         hadammo = other.ammo_rockets1;            
  751.         new = IT_GRENADE_LAUNCHER;
  752.         if (leave)
  753.             other.ammo_multi_rockets = other.ammo_multi_rockets + 3;
  754.         other.ammo_rockets1 = other.ammo_rockets1 + 5;
  755.     }
  756.     else if (self.classname == "weapon_lightning")
  757.     {
  758.         if (leave && (other.items & IT_LIGHTNING) )
  759.             return;
  760.         hadammo = other.ammo_rockets1;            
  761.         new = IT_LIGHTNING;
  762.         if (leave)
  763.             other.ammo_plasma = other.ammo_plasma + 5;
  764.         other.ammo_cells1 = other.ammo_cells1 + 15;
  765.     }
  766.     else
  767.         objerror ("weapon_touch: unknown classname");
  768.  
  769.     sprint (other, "You got the ");
  770.     sprint (other, self.netname);
  771.     sprint (other, "\n");
  772. // weapon touch sound
  773.     sound (other, CHAN_ITEM, "weapons/pkup.wav", 1, ATTN_NORM);
  774.     stuffcmd (other, "bf\n");
  775.  
  776.     bound_other_ammo ();
  777.  
  778. // change to the weapon
  779.     old = other.items;
  780.     other.items = other.items | new;
  781.  
  782.     EnableComboWeapons ( other );
  783.  
  784.     // PGM - fake picking up the plasma gun.
  785.     if (new == IT_LIGHTNING)
  786.     {
  787.         if (other.ammo_plasma > 0)
  788.             new = IT_PLASMA_GUN;
  789.     }
  790.     else if (new == IT_ROCKET_LAUNCHER)
  791.     {
  792.         if (other.ammo_multi_rockets > 0)
  793.             new = IT_MULTI_ROCKET;
  794.     }
  795.     else if (new == IT_GRENADE_LAUNCHER)
  796.     {
  797.         if (other.ammo_multi_rockets > 0)
  798.             new = IT_MULTI_GRENADE;
  799.     }
  800.     else if (new == IT_SUPER_NAILGUN)
  801.     {
  802.         if (other.ammo_lava_nails > 1)
  803.             new = IT_LAVA_SUPER_NAILGUN;
  804.     }
  805.     else if (new == IT_NAILGUN)
  806.     {
  807.         if (other.ammo_lava_nails > 0)
  808.             new = IT_LAVA_NAILGUN;
  809.     }
  810.     
  811.     
  812.     stemp = self;
  813.     self = other;
  814.  
  815.     if (!deathmatch)
  816.         self.weapon = new;
  817.     else
  818.         Deathmatch_Weapon (old, new);
  819.  
  820.     UpdateAmmoCounts ( self );
  821.     W_SetCurrentAmmo();
  822.  
  823.     self = stemp;
  824.  
  825.     if (leave)
  826.         return;
  827.  
  828. // remove it in single player, or setup for respawning in deathmatch
  829.     self.model = string_null;
  830.     self.solid = SOLID_NOT;
  831.     if (deathmatch == 1)
  832.          self.nextthink = time + 30;
  833.     self.think = SUB_regen;
  834.     
  835.     activator = other;
  836.     SUB_UseTargets();                // fire all targets / killtargets
  837. };
  838.  
  839.  
  840. /*QUAKED weapon_supershotgun (0 .5 .8) (-16 -16 0) (16 16 32)
  841. */
  842.  
  843. void() weapon_supershotgun =
  844. {
  845.     precache_model ("progs/g_shot.mdl");
  846.     setmodel (self, "progs/g_shot.mdl");
  847.     self.weapon = IT_SUPER_SHOTGUN;
  848.     self.netname = "Double-barrelled Shotgun";
  849.     self.touch = weapon_touch;
  850.     setsize (self, '-16 -16 0', '16 16 56');
  851.     StartItem ();
  852. };
  853.  
  854. /*QUAKED weapon_nailgun (0 .5 .8) (-16 -16 0) (16 16 32)
  855. */
  856.  
  857. void() weapon_nailgun =
  858. {
  859.     precache_model ("progs/g_nail.mdl");
  860.     setmodel (self, "progs/g_nail.mdl");
  861.     self.weapon = IT_NAILGUN;
  862.     self.netname = "nailgun";
  863.     self.touch = weapon_touch;
  864.     setsize (self, '-16 -16 0', '16 16 56');
  865.     StartItem ();
  866. };
  867.  
  868. /*QUAKED weapon_supernailgun (0 .5 .8) (-16 -16 0) (16 16 32)
  869. */
  870.  
  871. void() weapon_supernailgun =
  872. {
  873.     precache_model ("progs/g_nail2.mdl");
  874.     setmodel (self, "progs/g_nail2.mdl");
  875.     self.weapon = IT_SUPER_NAILGUN;
  876.     self.netname = "Super Nailgun";
  877.     self.touch = weapon_touch;
  878.     setsize (self, '-16 -16 0', '16 16 56');
  879.     StartItem ();
  880. };
  881.  
  882. /*QUAKED weapon_grenadelauncher (0 .5 .8) (-16 -16 0) (16 16 32)
  883. */
  884.  
  885. void() weapon_grenadelauncher =
  886. {
  887.     precache_model ("progs/g_rock.mdl");
  888.     setmodel (self, "progs/g_rock.mdl");
  889.     self.weapon = 3;
  890.     self.netname = "Grenade Launcher";
  891.     self.touch = weapon_touch;
  892.     setsize (self, '-16 -16 0', '16 16 56');
  893.     StartItem ();
  894. };
  895.  
  896. /*QUAKED weapon_rocketlauncher (0 .5 .8) (-16 -16 0) (16 16 32)
  897. */
  898.  
  899. void() weapon_rocketlauncher =
  900. {
  901.     precache_model ("progs/g_rock2.mdl");
  902.     setmodel (self, "progs/g_rock2.mdl");
  903.     self.weapon = 3;
  904.     self.netname = "Rocket Launcher";
  905.     self.touch = weapon_touch;
  906.     setsize (self, '-16 -16 0', '16 16 56');
  907.     StartItem ();
  908. };
  909.  
  910.  
  911. /*QUAKED weapon_lightning (0 .5 .8) (-16 -16 0) (16 16 32)
  912. */
  913.  
  914. void() weapon_lightning =
  915. {
  916.     precache_model ("progs/g_light.mdl");
  917.     setmodel (self, "progs/g_light.mdl");
  918.     self.weapon = 3;
  919.     self.netname = "Thunderbolt";
  920.     self.touch = weapon_touch;
  921.     setsize (self, '-16 -16 0', '16 16 56');
  922.     StartItem ();
  923. };
  924.  
  925.  
  926. /*
  927. ===============================================================================
  928.  
  929. AMMO
  930.  
  931. ===============================================================================
  932. */
  933.  
  934. // ### Rob;
  935. // items2 alternate rules changes
  936. float(float ammo_cur, float ammo_cap) ammo_leave =
  937. {
  938.     if (ammo_cur >= ammo_cap)
  939.         return TRUE;
  940.  
  941.     if (! deathmatch && (sp_altrules & SP_ITEMS2))
  942.     {
  943.         if (self.aflag > (ammo_cap - ammo_cur))
  944.             return TRUE;
  945.     }
  946.  
  947.     return FALSE;
  948. };
  949.  
  950.  
  951. void() ammo_touch =
  952. {
  953. local entity    stemp;
  954. local float        best;
  955.  
  956.     if (other.classname != "player")
  957.         return;
  958.     if (other.health <= 0)
  959.         return;
  960.  
  961. // if the player was using his best weapon, change up to the new one if better
  962.  
  963.     stemp = self;
  964.     self = other;
  965.     best = W_BestWeapon();
  966.     self = stemp;
  967.  
  968. // by this point, other is the player and self is the ammo pack. - PGM
  969.  
  970. // shotgun
  971.     if (self.weapon == 1)
  972.     {
  973.         if ( ammo_leave(other.ammo_shells1, 100) )
  974.             return;
  975.         other.ammo_shells1 = other.ammo_shells1 + self.aflag;
  976.     }
  977.  
  978. // spikes
  979.     if (self.weapon == 2)
  980.     {
  981.         if ( ammo_leave(other.ammo_nails1, 200) )
  982.             return;
  983.         other.ammo_nails1 = other.ammo_nails1 + self.aflag;
  984.     }
  985.  
  986. //    rockets
  987.     if (self.weapon == 3)
  988.     {
  989.         if ( ammo_leave(other.ammo_rockets1, 100) )
  990.             return;
  991.         other.ammo_rockets1 = other.ammo_rockets1 + self.aflag;
  992.     }
  993.  
  994. //    cells
  995.     if (self.weapon == 4)
  996.     {
  997.         if ( ammo_leave(other.ammo_cells1, 100) )
  998.             return;
  999.         other.ammo_cells1 = other.ammo_cells1 + self.aflag;
  1000.     }
  1001.  
  1002. //    lava spikes
  1003.     if (self.weapon == 5)
  1004.     {
  1005.         if ( ammo_leave(other.ammo_lava_nails, 200) )
  1006.             return;
  1007.         other.ammo_lava_nails = other.ammo_lava_nails + self.aflag;
  1008.     }
  1009.  
  1010. //    multi grenades
  1011.     if (self.weapon == 6)
  1012.     {
  1013.         if ( ammo_leave(other.ammo_multi_rockets, 100) )
  1014.             return;
  1015.         other.ammo_multi_rockets = other.ammo_multi_rockets + self.aflag;
  1016.     }
  1017.  
  1018. //    plasma
  1019.     if (self.weapon == 7)
  1020.     {
  1021.         if ( ammo_leave(other.ammo_plasma, 100) )
  1022.             return;
  1023.         other.ammo_plasma = other.ammo_plasma + self.aflag;
  1024.     }
  1025.  
  1026.     EnableComboWeapons ( other );
  1027.     UpdateAmmoCounts ( other );
  1028.  
  1029.     bound_other_ammo ();
  1030.  
  1031.     sprint (other, "You got the ");
  1032.     sprint (other, self.netname);
  1033.     sprint (other, "\n");
  1034. // ammo touch sound
  1035.     sound (other, CHAN_ITEM, "weapons/lock4.wav", 1, ATTN_NORM);
  1036.     stuffcmd (other, "bf\n");
  1037.  
  1038. // change to a better weapon if appropriate
  1039.  
  1040.     if ( other.weapon == best )
  1041.     {
  1042.         stemp = self;
  1043.         self = other;
  1044.         self.weapon = W_BestWeapon();
  1045.         W_SetCurrentAmmo ();
  1046.         self = stemp;
  1047.     }
  1048.  
  1049. // if changed current ammo, update it
  1050.     stemp = self;
  1051.     self = other;
  1052.     W_SetCurrentAmmo();
  1053.     self = stemp;
  1054.  
  1055. // remove it in single player, or setup for respawning in deathmatch
  1056.     self.model = string_null;
  1057.     self.solid = SOLID_NOT;
  1058.     if (deathmatch == 1)
  1059.         self.nextthink = time + 30;
  1060.     self.think = SUB_regen;
  1061.  
  1062.     activator = other;
  1063.     SUB_UseTargets();                // fire all targets / killtargets
  1064. };
  1065.  
  1066.  
  1067.  
  1068.  
  1069. float WEAPON_BIG2 = 1;
  1070.  
  1071. /*QUAKED item_shells (0 .5 .8) (0 0 0) (32 32 32) big
  1072. Small box is 20, Big box is 40.
  1073. */
  1074.  
  1075. void() item_shells =
  1076. {
  1077.     self.touch = ammo_touch;
  1078.  
  1079.     if (self.spawnflags & WEAPON_BIG2)
  1080.     {
  1081.         precache_model ("maps/b_shell1.bsp");
  1082.         setmodel (self, "maps/b_shell1.bsp");
  1083.         self.aflag = 40;
  1084.     }
  1085.     else
  1086.     {
  1087.         precache_model ("maps/b_shell0.bsp");
  1088.         setmodel (self, "maps/b_shell0.bsp");
  1089.         self.aflag = 20;
  1090.     }
  1091.     self.weapon = 1;
  1092.     self.netname = "shells";
  1093.     setsize (self, '0 0 0', '32 32 56');
  1094.     StartItem ();
  1095. };
  1096.  
  1097. /*QUAKED item_spikes (0 .5 .8) (0 0 0) (32 32 32) big
  1098. Small box is 25, Big box is 50.
  1099. */
  1100.  
  1101. void() item_spikes =
  1102. {
  1103.     self.touch = ammo_touch;
  1104.  
  1105.     if (self.spawnflags & WEAPON_BIG2)
  1106.     {
  1107.         precache_model ("maps/b_nail1.bsp");
  1108.         setmodel (self, "maps/b_nail1.bsp");
  1109.         self.aflag = 50;
  1110.     }
  1111.     else
  1112.     {
  1113.         precache_model ("maps/b_nail0.bsp");
  1114.         setmodel (self, "maps/b_nail0.bsp");
  1115.         self.aflag = 25;
  1116.     }
  1117.     self.weapon = 2;
  1118.     self.netname = "nails";
  1119.     setsize (self, '0 0 0', '32 32 56');
  1120.     StartItem ();
  1121. };
  1122.  
  1123. /*QUAKED item_lava_spikes (0 .5 .8) (0 0 0) (32 32 32) big
  1124. Small box is 25, Big box is 50.
  1125. */
  1126.  
  1127. void() item_lava_spikes =
  1128. {
  1129.     self.touch = ammo_touch;
  1130.  
  1131.     if (self.spawnflags & WEAPON_BIG2)
  1132.     {
  1133.         precache_model ("maps/b_lnail1.bsp");
  1134.         setmodel (self, "maps/b_lnail1.bsp");
  1135.         self.aflag = 50;
  1136.     }
  1137.     else
  1138.     {
  1139.         precache_model ("maps/b_lnail0.bsp");
  1140.         setmodel (self, "maps/b_lnail0.bsp");
  1141.         self.aflag = 25;
  1142.     }
  1143.     self.weapon = 5;
  1144.     self.netname = "lava nails";
  1145.     setsize (self, '0 0 0', '32 32 56');
  1146.     StartItem ();
  1147. };
  1148.  
  1149. /*QUAKED item_rockets (0 .5 .8) (0 0 0) (32 32 32) big
  1150. Small box is 5, Big box is 10.
  1151. */
  1152.  
  1153. void() item_rockets =
  1154. {
  1155.     self.touch = ammo_touch;
  1156.  
  1157.     if (self.spawnflags & WEAPON_BIG2)
  1158.     {
  1159.         precache_model ("maps/b_rock1.bsp");
  1160.         setmodel (self, "maps/b_rock1.bsp");
  1161.         self.aflag = 10;
  1162.     }
  1163.     else
  1164.     {
  1165.         precache_model ("maps/b_rock0.bsp");
  1166.         setmodel (self, "maps/b_rock0.bsp");
  1167.         self.aflag = 5;
  1168.     }
  1169.     self.weapon = 3;
  1170.     self.netname = "rockets";
  1171.     setsize (self, '0 0 0', '32 32 56');
  1172.     StartItem ();
  1173. };
  1174.  
  1175. /*QUAKED item_multi_rockets (0 .5 .8) (0 0 0) (32 32 32) big
  1176. Small box is 5, Big box is 10.
  1177. */
  1178.  
  1179. void() item_multi_rockets =
  1180. {
  1181.     self.touch = ammo_touch;
  1182.  
  1183.     if (self.spawnflags & WEAPON_BIG2)
  1184.     {
  1185.         precache_model ("maps/b_mrock1.bsp");
  1186.         setmodel (self, "maps/b_mrock1.bsp");
  1187.         self.aflag = 10;
  1188.     }
  1189.     else
  1190.     {
  1191.         precache_model ("maps/b_mrock0.bsp");
  1192.         setmodel (self, "maps/b_mrock0.bsp");
  1193.         self.aflag = 5;
  1194.     }
  1195.     self.weapon = 6;
  1196.     self.netname = "multi rockets";
  1197.     setsize (self, '0 0 0', '32 32 56');
  1198.     StartItem ();
  1199. };
  1200.  
  1201.  
  1202. /*QUAKED item_cells (0 .5 .8) (0 0 0) (32 32 32) big
  1203. Small box is 6, Big box is 12.
  1204. */
  1205. void() item_cells =
  1206. {
  1207.     self.touch = ammo_touch;
  1208.  
  1209.     if (self.spawnflags & WEAPON_BIG2)
  1210.     {
  1211.         precache_model ("maps/b_batt1.bsp");
  1212.         setmodel (self, "maps/b_batt1.bsp");
  1213.         self.aflag = 12;
  1214.     }
  1215.     else
  1216.     {
  1217.         precache_model ("maps/b_batt0.bsp");
  1218.         setmodel (self, "maps/b_batt0.bsp");
  1219.         self.aflag = 6;
  1220.     }
  1221.     self.weapon = 4;
  1222.     self.netname = "cells";
  1223.     setsize (self, '0 0 0', '32 32 56');
  1224.     StartItem ();
  1225. };
  1226.  
  1227. /*QUAKED item_plasma (0 .5 .8) (0 0 0) (32 32 32) big
  1228. Small box is 6, Big box is 12.
  1229. */
  1230. void() item_plasma =
  1231. {
  1232.     self.touch = ammo_touch;
  1233.  
  1234.     if (self.spawnflags & WEAPON_BIG2)
  1235.     {
  1236.         precache_model ("maps/b_plas1.bsp");
  1237.         setmodel (self, "maps/b_plas1.bsp");
  1238.         self.aflag = 12;
  1239.     }
  1240.     else
  1241.     {
  1242.         precache_model ("maps/b_plas0.bsp");
  1243.         setmodel (self, "maps/b_plas0.bsp");
  1244.         self.aflag = 6;
  1245.     }
  1246.     self.weapon = 7;
  1247.     self.netname = "plasma";
  1248.     setsize (self, '0 0 0', '32 32 56');
  1249.     StartItem ();
  1250. };
  1251.  
  1252.  
  1253. /*QUAKED item_weapon (0 .5 .8) (0 0 0) (32 32 32) shotgun rocket spikes big
  1254. DO NOT USE THIS!!!! IT WILL BE REMOVED!
  1255. */
  1256.  
  1257. float WEAPON_SHOTGUN = 1;
  1258. float WEAPON_ROCKET = 2;
  1259. float WEAPON_SPIKES = 4;
  1260. float WEAPON_BIG = 8;
  1261. void() item_weapon =
  1262. {
  1263.     self.touch = ammo_touch;
  1264.  
  1265.     if (self.spawnflags & WEAPON_SHOTGUN)
  1266.     {
  1267.         if (self.spawnflags & WEAPON_BIG)
  1268.         {
  1269.             precache_model ("maps/b_shell1.bsp");
  1270.             setmodel (self, "maps/b_shell1.bsp");
  1271.             self.aflag = 40;
  1272.         }
  1273.         else
  1274.         {
  1275.             precache_model ("maps/b_shell0.bsp");
  1276.             setmodel (self, "maps/b_shell0.bsp");
  1277.             self.aflag = 20;
  1278.         }
  1279.         self.weapon = 1;
  1280.         self.netname = "shells";
  1281.     }
  1282.  
  1283.     if (self.spawnflags & WEAPON_SPIKES)
  1284.     {
  1285.         if (self.spawnflags & WEAPON_BIG)
  1286.         {
  1287.             precache_model ("maps/b_nail1.bsp");
  1288.             setmodel (self, "maps/b_nail1.bsp");
  1289.             self.aflag = 40;
  1290.         }
  1291.         else
  1292.         {
  1293.             precache_model ("maps/b_nail0.bsp");
  1294.             setmodel (self, "maps/b_nail0.bsp");
  1295.             self.aflag = 20;
  1296.         }
  1297.         self.weapon = 2;
  1298.         self.netname = "spikes";
  1299.     }
  1300.  
  1301.     if (self.spawnflags & WEAPON_ROCKET)
  1302.     {
  1303.         if (self.spawnflags & WEAPON_BIG)
  1304.         {
  1305.             precache_model ("maps/b_rock1.bsp");
  1306.             setmodel (self, "maps/b_rock1.bsp");
  1307.             self.aflag = 10;
  1308.         }
  1309.         else
  1310.         {
  1311.             precache_model ("maps/b_rock0.bsp");
  1312.             setmodel (self, "maps/b_rock0.bsp");
  1313.             self.aflag = 5;
  1314.         }
  1315.         self.weapon = 3;
  1316.         self.netname = "rockets";
  1317.     }
  1318.     
  1319.     setsize (self, '0 0 0', '32 32 56');
  1320.     StartItem ();
  1321. };
  1322.  
  1323.  
  1324. /*
  1325. ===============================================================================
  1326.  
  1327. KEYS
  1328.  
  1329. ===============================================================================
  1330. */
  1331.  
  1332. void() key_touch =
  1333. {
  1334. local entity    stemp;
  1335. local float        best;
  1336.  
  1337.     if (other.classname != "player")
  1338.         return;
  1339.     if (other.health <= 0)
  1340.         return;
  1341.     if (other.items & self.items)
  1342.         return;
  1343.  
  1344.     sprint (other, "You got the ");
  1345.     sprint (other, self.netname);
  1346.     sprint (other,"\n");
  1347.  
  1348.     sound (other, CHAN_ITEM, self.noise, 1, ATTN_NORM);
  1349.     stuffcmd (other, "bf\n");
  1350.     other.items = other.items | self.items;
  1351.  
  1352.     if (!coop)
  1353.     {    
  1354.         self.solid = SOLID_NOT;
  1355.         self.model = string_null;
  1356.     }
  1357.  
  1358.     activator = other;
  1359.     SUB_UseTargets();                // fire all targets / killtargets
  1360. };
  1361.  
  1362.  
  1363. void() key_setsounds =
  1364. {
  1365.     if (world.worldtype == 0)
  1366.     {
  1367.         precache_sound ("misc/medkey.wav");
  1368.         self.noise = "misc/medkey.wav";
  1369.     }
  1370.     if (world.worldtype == 1)
  1371.     {
  1372.         precache_sound ("misc/runekey.wav");
  1373.         self.noise = "misc/runekey.wav";
  1374.     }
  1375.     if (world.worldtype == 2)
  1376.     {
  1377.         precache_sound2 ("misc/basekey.wav");
  1378.         self.noise = "misc/basekey.wav";
  1379.     }
  1380. };
  1381.  
  1382. /*QUAKED item_key1 (0 .5 .8) (-16 -16 -24) (16 16 32)
  1383. SILVER key
  1384. In order for keys to work
  1385. you MUST set your maps
  1386. worldtype to one of the
  1387. following:
  1388. 0: medieval
  1389. 1: metal
  1390. 2: base
  1391. */
  1392.  
  1393. void() item_key1 =
  1394. {
  1395.     if (world.worldtype == 0)
  1396.     {
  1397.         precache_model ("progs/w_s_key.mdl");
  1398.         setmodel (self, "progs/w_s_key.mdl");
  1399.         self.netname = "silver key";
  1400.     }
  1401.     else if (world.worldtype == 1)
  1402.     {
  1403.         precache_model ("progs/m_s_key.mdl");
  1404.         setmodel (self, "progs/m_s_key.mdl");
  1405.         self.netname = "silver runekey";
  1406.     }
  1407.     else if (world.worldtype == 2)
  1408.     {
  1409.         precache_model2 ("progs/b_s_key.mdl");
  1410.         setmodel (self, "progs/b_s_key.mdl");
  1411.         self.netname = "silver keycard";
  1412.     }
  1413.     key_setsounds();
  1414.     self.touch = key_touch;
  1415.     self.items = IT_KEY1;
  1416.     setsize (self, '-16 -16 -24', '16 16 32');
  1417.     StartItem ();
  1418. };
  1419.  
  1420. /*QUAKED item_key2 (0 .5 .8) (-16 -16 -24) (16 16 32)
  1421. GOLD key
  1422. In order for keys to work
  1423. you MUST set your maps
  1424. worldtype to one of the
  1425. following:
  1426. 0: medieval
  1427. 1: metal
  1428. 2: base
  1429. */
  1430.  
  1431. void() item_key2 =
  1432. {
  1433.     if (world.worldtype == 0)
  1434.     {
  1435.         precache_model ("progs/w_g_key.mdl");
  1436.         setmodel (self, "progs/w_g_key.mdl");
  1437.         self.netname = "gold key";
  1438.     }
  1439.     if (world.worldtype == 1)
  1440.     {
  1441.         precache_model ("progs/m_g_key.mdl");
  1442.         setmodel (self, "progs/m_g_key.mdl");
  1443.         self.netname = "gold runekey";
  1444.     }
  1445.     if (world.worldtype == 2)
  1446.     {
  1447.         precache_model2 ("progs/b_g_key.mdl");
  1448.         setmodel (self, "progs/b_g_key.mdl");
  1449.         self.netname = "gold keycard";
  1450.     }
  1451.     key_setsounds();
  1452.     self.touch = key_touch;
  1453.     self.items = IT_KEY2;
  1454.     setsize (self, '-16 -16 -24', '16 16 32');
  1455.     StartItem ();
  1456. };
  1457.  
  1458.  
  1459.  
  1460. /*
  1461. ===============================================================================
  1462.  
  1463. END OF LEVEL RUNES
  1464.  
  1465. ===============================================================================
  1466. */
  1467.  
  1468. void() sigil_touch =
  1469. {
  1470. local entity    stemp;
  1471. local float        best;
  1472.  
  1473.     if (other.classname != "player")
  1474.         return;
  1475.     if (other.health <= 0)
  1476.         return;
  1477.  
  1478.     centerprint (other, "You got the rune!");
  1479.  
  1480.     sound (other, CHAN_ITEM, self.noise, 1, ATTN_NORM);
  1481.     stuffcmd (other, "bf\n");
  1482.     self.solid = SOLID_NOT;
  1483.     self.model = string_null;
  1484.     serverflags = serverflags | (self.spawnflags & 15);
  1485.     self.classname = "";        // so rune doors won't find it
  1486.     
  1487.     activator = other;
  1488.     SUB_UseTargets();                // fire all targets / killtargets
  1489. };
  1490.  
  1491.  
  1492. /*QUAKED item_sigil (0 .5 .8) (-16 -16 -24) (16 16 32) E1 E2 E3 E4
  1493. End of level sigil, pick up to end episode and return to jrstart.
  1494. */
  1495.  
  1496. void() item_sigil =
  1497. {
  1498.     if (!self.spawnflags)
  1499.         objerror ("no spawnflags");
  1500.  
  1501.     precache_sound ("misc/runekey.wav");
  1502.     self.noise = "misc/runekey.wav";
  1503.  
  1504.     if (self.spawnflags & 1)
  1505.     {
  1506.         precache_model ("progs/end1.mdl");
  1507.         setmodel (self, "progs/end1.mdl");
  1508.     }
  1509.     if (self.spawnflags & 2)
  1510.     {
  1511.         precache_model2 ("progs/end2.mdl");
  1512.         setmodel (self, "progs/end2.mdl");
  1513.     }
  1514.     if (self.spawnflags & 4)
  1515.     {
  1516.         precache_model2 ("progs/end3.mdl");
  1517.         setmodel (self, "progs/end3.mdl");
  1518.     }
  1519.     if (self.spawnflags & 8)
  1520.     {
  1521.         precache_model2 ("progs/end4.mdl");
  1522.         setmodel (self, "progs/end4.mdl");
  1523.     }
  1524.     
  1525.     self.touch = sigil_touch;
  1526.     setsize (self, '-16 -16 -24', '16 16 32');
  1527.     StartItem ();
  1528. };
  1529.  
  1530. /*
  1531. ===============================================================================
  1532.  
  1533. POWERUPS
  1534.  
  1535. ===============================================================================
  1536. */
  1537.  
  1538. void() powerup_touch;
  1539. void() random_regen;
  1540.  
  1541. void() powerup_touch =
  1542. {
  1543. local entity    stemp;
  1544. local float        best;
  1545.  
  1546.     if (other.classname != "player")
  1547.         return;
  1548.     if (other.health <= 0)
  1549.         return;
  1550.  
  1551.     sprint (other, "You got the ");
  1552.     sprint (other, self.netname);
  1553.     sprint (other,"\n");
  1554.  
  1555.     if (deathmatch)
  1556.     {
  1557.         self.mdl = self.model;
  1558.         
  1559.         if (self.classname == "item_random_powerup")
  1560.         {
  1561.             self.nextthink = time + 30;
  1562.             self.think = random_regen;
  1563.         }
  1564.         else 
  1565.         {
  1566.             if ((self.classname == "item_artifact_invulnerability") ||
  1567.                 (self.classname == "item_artifact_invisibility"))
  1568.                 self.nextthink = time + 60*5;
  1569.             else
  1570.                 self.nextthink = time + 60;
  1571.         
  1572.             self.think = SUB_regen;
  1573.         }
  1574.     }    
  1575.  
  1576.     sound (other, CHAN_VOICE, self.noise, 1, ATTN_NORM);
  1577.     stuffcmd (other, "bf\n");
  1578.     self.solid = SOLID_NOT;
  1579.     other.items = other.items | self.items;
  1580.     self.model = string_null;
  1581.  
  1582. // do the apropriate action
  1583. //    if (self.classname == "item_artifact_envirosuit")
  1584.     if (self.netname == "Biosuit")
  1585.     {
  1586.         other.rad_time = 1;
  1587.         other.radsuit_finished = time + 30;
  1588.     }
  1589.     
  1590. //    if (self.classname == "item_artifact_invulnerability")
  1591.     if (self.netname == "Pentagram of Protection")
  1592.     {
  1593.         other.invincible_time = 1;
  1594.         other.invincible_finished = time + 30;
  1595.     }
  1596.     
  1597. //    if (self.classname == "item_artifact_invisibility")
  1598.     if (self.netname == "Ring of Shadows")
  1599.     {
  1600.         other.invisible_time = 1;
  1601.         other.invisible_finished = time + 30;
  1602.     }
  1603.  
  1604. //    if (self.classname == "item_artifact_super_damage")
  1605.     if (self.netname == "Quad Damage")
  1606.     {
  1607.         other.super_time = 1;
  1608.         other.super_damage_finished = time + 30;
  1609.     }    
  1610.  
  1611.     activator = other;
  1612.     SUB_UseTargets();                // fire all targets / killtargets
  1613. };
  1614.  
  1615.  
  1616.  
  1617. /*QUAKED item_artifact_invulnerability (0 .5 .8) (-16 -16 -24) (16 16 32)
  1618. Player is invulnerable for 30 seconds
  1619. */
  1620. void() item_artifact_invulnerability =
  1621. {
  1622.     self.touch = powerup_touch;
  1623.  
  1624.     precache_model ("progs/invulner.mdl");
  1625.     precache_sound ("items/protect.wav");
  1626.     precache_sound ("items/protect2.wav");
  1627.     precache_sound ("items/protect3.wav");
  1628.     self.noise = "items/protect.wav";
  1629.     setmodel (self, "progs/invulner.mdl");
  1630.     self.netname = "Pentagram of Protection";
  1631.     self.items = IT_INVULNERABILITY;
  1632.     setsize (self, '-16 -16 -24', '16 16 32');
  1633.     StartItem ();
  1634. };
  1635.  
  1636. /*QUAKED item_artifact_envirosuit (0 .5 .8) (-16 -16 -24) (16 16 32)
  1637. Player takes no damage from water or slime for 30 seconds
  1638. */
  1639. void() item_artifact_envirosuit =
  1640. {
  1641.     self.touch = powerup_touch;
  1642.  
  1643.     precache_model ("progs/suit.mdl");
  1644.     precache_sound ("items/suit.wav");
  1645.     precache_sound ("items/suit2.wav");
  1646.     self.noise = "items/suit.wav";
  1647.     setmodel (self, "progs/suit.mdl");
  1648.     self.netname = "Biosuit";
  1649.     self.items = IT_SUIT;
  1650.     setsize (self, '-16 -16 -24', '16 16 32');
  1651.     StartItem ();
  1652. };
  1653.  
  1654.  
  1655. /*QUAKED item_artifact_invisibility (0 .5 .8) (-16 -16 -24) (16 16 32)
  1656. Player is invisible for 30 seconds
  1657. */
  1658. void() item_artifact_invisibility =
  1659. {
  1660.     self.touch = powerup_touch;
  1661.  
  1662.     precache_model ("progs/invisibl.mdl");
  1663.     precache_sound ("items/inv1.wav");
  1664.     precache_sound ("items/inv2.wav");
  1665.     precache_sound ("items/inv3.wav");
  1666.     self.noise = "items/inv1.wav";
  1667.     setmodel (self, "progs/invisibl.mdl");
  1668.     self.netname = "Ring of Shadows";
  1669.     self.items = IT_INVISIBILITY;
  1670.     setsize (self, '-16 -16 -24', '16 16 32');
  1671.     StartItem ();
  1672. };
  1673.  
  1674.  
  1675. /*QUAKED item_artifact_super_damage (0 .5 .8) (-16 -16 -24) (16 16 32)
  1676. The next attack from the player will do 4x damage
  1677. */
  1678. void() item_artifact_super_damage =
  1679. {
  1680.     self.touch = powerup_touch;
  1681.  
  1682.     precache_model ("progs/quaddama.mdl");
  1683.     precache_sound ("items/damage.wav");
  1684.     precache_sound ("items/damage2.wav");
  1685.     precache_sound ("items/damage3.wav");
  1686.     self.noise = "items/damage.wav";
  1687.     setmodel (self, "progs/quaddama.mdl");
  1688.     self.netname = "Quad Damage";
  1689.     self.items = IT_QUAD;
  1690.     setsize (self, '-16 -16 -24', '16 16 32');
  1691.     StartItem ();
  1692. };
  1693.  
  1694.  
  1695. /*
  1696. ===============================================================================
  1697.  
  1698. PLAYER BACKPACKS
  1699.  
  1700. ===============================================================================
  1701. */
  1702.  
  1703. void() BackpackTouch =
  1704. {
  1705.     local string    s;
  1706.     local    float    best, old, new;
  1707.     local        entity    stemp;
  1708.     local    float    acount;
  1709.     
  1710.     if (other.classname != "player")
  1711.         return;
  1712.     if (other.health <= 0)
  1713.         return;
  1714.         
  1715. //ZOID--
  1716.     // Don't let the owner pick up his own backpack for a second.
  1717.     if ((other == self.owner) && ((self.nextthink - time) > 119))
  1718.         return;
  1719. //--ZOID
  1720.  
  1721.     acount = 0;
  1722.     sprint (other, "You get ");
  1723.  
  1724.     if (self.items)
  1725.         if ((other.items & self.items) == 0)
  1726.         {
  1727.             acount = 1;
  1728.             sprint (other, "the ");
  1729.             sprint (other, self.netname);
  1730.         }
  1731.  
  1732. // if the player was using his best weapon, change up to the new one if better
  1733.     stemp = self;
  1734.     self = other;
  1735.     best = W_BestWeapon();
  1736.     self = stemp;
  1737.  
  1738. // change weapons
  1739.     other.ammo_shells1 = other.ammo_shells1 + self.ammo_shells1;
  1740.     other.ammo_nails1 = other.ammo_nails1 + self.ammo_nails1;
  1741.     other.ammo_rockets1 = other.ammo_rockets1 + self.ammo_rockets1;
  1742.     other.ammo_cells1 = other.ammo_cells1 + self.ammo_cells1;
  1743.  
  1744.     other.ammo_lava_nails = other.ammo_lava_nails + self.ammo_lava_nails;
  1745.     other.ammo_multi_rockets = other.ammo_multi_rockets +
  1746.                                     self.ammo_multi_rockets;
  1747.     other.ammo_plasma = other.ammo_plasma + self.ammo_plasma;
  1748.     
  1749.     new = self.items;
  1750.     if (!new)
  1751.         new = other.weapon;
  1752.     old = other.items;
  1753.     other.items = other.items | new;
  1754.     
  1755.     bound_other_ammo ();
  1756.  
  1757.     if (self.ammo_shells1)
  1758.     {
  1759.         if (acount)
  1760.             sprint(other, ", ");
  1761.         acount = 1;
  1762.         s = ftos(self.ammo_shells1);
  1763.         sprint (other, s);
  1764.         sprint (other, " shells");
  1765.     }
  1766.     if (self.ammo_nails1)
  1767.     {
  1768.         if (acount)
  1769.             sprint(other, ", ");
  1770.         acount = 1;
  1771.         s = ftos(self.ammo_nails1);
  1772.         sprint (other, s);
  1773.         sprint (other, " nails");
  1774.     }
  1775.     if (self.ammo_rockets1)
  1776.     {
  1777.         if (acount)
  1778.             sprint(other, ", ");
  1779.         acount = 1;
  1780.         s = ftos(self.ammo_rockets1);
  1781.         sprint (other, s);
  1782.         sprint (other, " rockets");
  1783.     }
  1784.     if (self.ammo_cells1)
  1785.     {
  1786.         if (acount)
  1787.             sprint(other, ", ");
  1788.         acount = 1;
  1789.         s = ftos(self.ammo_cells1);
  1790.         sprint (other, s);
  1791.         sprint (other, " cells");
  1792.     }
  1793.     if (self.ammo_lava_nails)
  1794.     {
  1795.         if (acount)
  1796.             sprint(other, ", ");
  1797.         acount = 1;
  1798.         s = ftos(self.ammo_lava_nails);
  1799.         sprint (other, s);
  1800.         sprint (other, " lava nails");
  1801.     }
  1802.     if (self.ammo_multi_rockets)
  1803.     {
  1804.         if (acount)
  1805.             sprint(other, ", ");
  1806.         acount = 1;
  1807.         s = ftos(self.ammo_multi_rockets);
  1808.         sprint (other, s);
  1809.         sprint (other, " multi rockets");
  1810.     }
  1811.     if (self.ammo_plasma)
  1812.     {
  1813.         if (acount)
  1814.             sprint(other, ", ");
  1815.         acount = 1;
  1816.         s = ftos(self.ammo_plasma);
  1817.         sprint (other, s);
  1818.         sprint (other, " plasma balls");
  1819.     }
  1820.     
  1821.     sprint (other, "\n");
  1822. // backpack touch sound
  1823.     sound (other, CHAN_ITEM, "weapons/lock4.wav", 1, ATTN_NORM);
  1824.     stuffcmd (other, "bf\n");
  1825.  
  1826. // remove the backpack, change self to the player
  1827.     remove(self);
  1828.     self = other;
  1829.  
  1830. // fixme -- move this to after weapon choice if problematic.
  1831.     EnableComboWeapons ( self );
  1832.  
  1833. // change to the weapon
  1834.     if (!deathmatch)
  1835.         self.weapon = new;
  1836.     else
  1837.         Deathmatch_Weapon (old, new);
  1838.  
  1839. //    EnableComboWeapons ( self );
  1840.     UpdateAmmoCounts (self);
  1841.     
  1842.     W_SetCurrentAmmo ();
  1843. };
  1844.  
  1845. /*
  1846. ===============
  1847. DropBackpack
  1848. ===============
  1849. */
  1850. void() DropBackpack =
  1851. {
  1852.     local entity    item;
  1853.  
  1854.     // this is to compensate for the new way we're hacking the ammo
  1855.     // counts. If they're monsters, just copy shells->shells1 etc.
  1856.     if (self.flags & FL_MONSTER)
  1857.     {
  1858.         self.ammo_shells1 = self.ammo_shells;
  1859.         self.ammo_nails1 = self.ammo_nails;
  1860.         self.ammo_rockets1 = self.ammo_rockets;
  1861.         self.ammo_cells1 = self.ammo_cells;
  1862.     }
  1863.     
  1864.     if (!(self.ammo_shells1 + self.ammo_nails1 + self.ammo_rockets1 + 
  1865.             self.ammo_cells1 + self.ammo_lava_nails + self.ammo_multi_rockets))
  1866.         return;    // nothing in it
  1867.  
  1868.     item = spawn();
  1869.     item.origin = self.origin - '0 0 24';
  1870.     
  1871.     item.items = self.weapon;
  1872.     if (item.items == IT_AXE)
  1873.         item.netname = "Axe";
  1874.     else if (item.items == IT_SHOTGUN)
  1875.         item.netname = "Shotgun";
  1876.     else if (item.items == IT_SUPER_SHOTGUN)
  1877.         item.netname = "Double-barrelled Shotgun";
  1878.     else if (item.items == IT_NAILGUN)
  1879.         item.netname = "Nailgun";
  1880.     else if (item.items == IT_SUPER_NAILGUN)
  1881.         item.netname = "Super Nailgun";
  1882.     else if (item.items == IT_GRENADE_LAUNCHER)
  1883.         item.netname = "Grenade Launcher";
  1884.     else if (item.items == IT_ROCKET_LAUNCHER)
  1885.         item.netname = "Rocket Launcher";
  1886.     else if (item.items == IT_LIGHTNING)
  1887.         item.netname = "Thunderbolt";    
  1888.     else if (item.items == IT_LAVA_NAILGUN)
  1889.     {
  1890.         item.netname = "Lava Nail Gun";    
  1891.         item.items = IT_NAILGUN;
  1892.     }
  1893.     else if (item.items == IT_LAVA_SUPER_NAILGUN)
  1894.     {
  1895.         item.netname = "Super Lava Nail Gun";    
  1896.         item.items = IT_SUPER_NAILGUN;
  1897.     }
  1898.     else if (item.items == IT_MULTI_GRENADE)
  1899.     {
  1900.         item.netname = "Multi Grenade Launcher";    
  1901.         item.items = IT_GRENADE_LAUNCHER;
  1902.     }
  1903.     else if (item.items == IT_MULTI_ROCKET)
  1904.     {
  1905.         item.netname = "Multi Rocket Launcher";    
  1906.         item.items = IT_ROCKET_LAUNCHER;
  1907.     }
  1908.     else if (item.items == IT_PLASMA_GUN)
  1909.     {
  1910.         item.netname = "Plasma Gun";    
  1911.         item.items = IT_LIGHTNING;
  1912.     }
  1913.     else
  1914.         item.netname = "";
  1915.     
  1916.     item.ammo_shells1 = self.ammo_shells1;
  1917.     item.ammo_nails1 = self.ammo_nails1;
  1918.     item.ammo_rockets1 = self.ammo_rockets1;
  1919.     item.ammo_cells1 = self.ammo_cells1;
  1920.     item.ammo_lava_nails = self.ammo_lava_nails;
  1921.     item.ammo_multi_rockets = self.ammo_multi_rockets;
  1922.     item.ammo_plasma = self.ammo_plasma;
  1923.     
  1924.     item.velocity_z = 300;
  1925.     item.velocity_x = -100 + (random() * 200);
  1926.     item.velocity_y = -100 + (random() * 200);
  1927.     
  1928.     item.flags = FL_ITEM;
  1929.     item.solid = SOLID_TRIGGER;
  1930.     item.movetype = MOVETYPE_TOSS;
  1931.     setmodel (item, "progs/backpack.mdl");
  1932.     setsize (item, '-16 -16 0', '16 16 56');
  1933.     item.touch = BackpackTouch;
  1934.     
  1935.     item.nextthink = time + 120;    // remove after 2 minutes
  1936.     item.think = SUB_Remove;
  1937. };
  1938.